all files / src/ common.ts

82.22% Statements 37/45
76% Branches 19/25
85.71% Functions 6/7
85% Lines 34/40
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102  1× 1× 1× 1×                 1×                             1× 1× 12×     12×   1× 1×           5×       532417× 309871× 309871× 242143×   67728×       2×       1067772× 1067760×   613613×   454147×       2×                 2× 70× 70× 70× 24×     24×     24×             1× 24× 206× 24×        
import { Calendar } from './calendar';
import { JulianDate } from "./julian-date";
import { GregorianDate } from "./gregorian-date";
import * as XRegExp from 'xregexp';
import { fromRomanNumber } from './roman';
 
export type JulianDays = {
    days: number,
    unknownYear: boolean,
    unknownMonth: boolean,
    unknownDay: boolean
}
 
const MonthPatterns: { [date: number]: string } =
{
    1: '([ij]an(uar(y|ii?)|)|janvier)',
    2: '(feb(ruar[yi]?|r|)|fevrier)',
    3: '(march|mars|marti[ia]s?|mart?)',
    4: '(a[pv]ril|aprilis|apr)',
    5: '(ma[ijy]|maji)',
    6: '[ij]ui?n(ias|ii|e|)',
    7: '([ij]uillet|[ij]ul[iay]s?)',
    8: '(se[cxk]t?|august(us|i|)|ao[uû]s?t|aug)',
    9: 'sep(ti?emb(er|re|r|)|t|)',
    10: 'o[ck]t(ob(er|re|r|)|)',
    11: 'nov(emb(er|re|ris|r|)|)',
    12: 'de[ck](emb(er|re|ris|r|)|)',
}
let CompiledMonthPatterns: { [date: number]: RegExp } = {}
for (let month = 1; month <= 12; month++) {
    CompiledMonthPatterns[month] = new RegExp(`^${MonthPatterns[month]}\.?$`, 'i');
}
 
const AnyMonthPattern = `(${Object.keys(MonthPatterns).map((_, index) => MonthPatterns[index + 1]).join('|')})\.?`;
// Roman or Arabic number
const NumberPattern = '([MDCLXVI]( ?[MDCLXVI])*|[0-9]+)';
const DateFormats: RegExp[] = [
    '^(?<month>{month}) (?<day>{day})[\.,] (?<year>{year})\.?$',
    '^(?<month>{month}) (?<day>{day})(st|nd|rd|th)[,\.]? (?<year>{year})\.?$',
    '^(ad|) ?(?<day>{day})[\.,]? ?(?<month>{month})[\. ](ao\.?|a\.?c\.?|anno|an\.? christi|an\.?|a\.?|) ?(?<year>{year})\.?$',
    '^(le|ce|) ?(?<day>{day})\.? (de |d[’\']|)(?<month>{month})(,? l[’\']an|\.?) (?<year>{year})\.?$',
    '^[aàá]? ?(?<day>{day})\.? de (?<month>{month}) del? a[nn̄n̄]*o de (?<year>{year})\.?$'
].map((pattern) => XRegExp(pattern.replace('{month}', AnyMonthPattern)
    .replace('{day}', NumberPattern)
    .replace('{year}', NumberPattern), 'i'));
 
export function isLeapYear(year: number | undefined, calendar: Calendar = 'gregorian') {
    Iif (year === undefined) { return false; }
    if (calendar == 'gregorian') {
        return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
    } else {
        return year % 4 === 0 || year <= 0;
    }
}
 
export function createDate(
    year: number | undefined,
    month: number | undefined,
    day: number | undefined,
    calendar: Calendar = 'gregorian') {
    switch (calendar) {
        case 'gregorian':
            return new GregorianDate(year, month, day);
        case 'julian':
            return new JulianDate(year, month, day);
    }
}
 
export function createDateFromString(text: string, calendar: Calendar = 'gregorian') {
    switch (calendar) {
        case 'gregorian':
            return GregorianDate.fromString(text);
        case 'julian':
            return JulianDate.fromString(text);
    }
}
 
export function parseDateString(text: string) {
    for (const format of DateFormats) {
        const match = XRegExp.exec(text, format) as any;
        if (match) {
            const day = fromRomanNumber(match['day']),
                month = parseMonthString(match['month']),
                year = fromRomanNumber(match['year']);
            Iif (month === null) {
                return null;
            }
            return { day, month, year };
        }
    }
 
    return null;
}
 
function parseMonthString(text: string) {
    for (let month = 1; month <= 12; month++) {
        if (CompiledMonthPatterns[month].test(text)) {
            return month;
        }
    }
    return null;
}